import Router, { RouteConfig } from 'vue-router'
import Layout from '../layout/index.vue'
import { getDataType } from '.'
import { isNotEmpty } from './validate'

/*
  name:'router-name'             the name field is required when using <keep-alive>, it should also match its component's name property
  redirect:                      if set to 'noredirect', no redirect action will be trigger when clicking the breadcrumb
  meta: {
    subsystem: ''                所属子系统
    whiter: false                是否在白名单中
    roles: ['admin', 'editor']   will control the page roles (allow setting multiple roles)
    title: 'title'               the name showed in subMenu and breadcrumb (recommend set)
    icon: 'svg-name'             the icon showed in the sidebar
    hidden: true                 if true, this route will not show in the sidebar (default is false)
    alwaysShow: true             if true, will always show the root menu (default is false)
                                 if false, hide the root menu when has less or equal than one children route
    breadcrumb: false            if false, the item will be hidden in breadcrumb (default is true)
    noCache: true                if true, the page will not be cached (default is false)
    affix: true                  if true, the tag will affix in the tags-view
    activeMenu: '/example/list'  if set path, the sidebar will highlight the path you set
  }
*/
export const constantRoutes: RouteConfig[] = [
  {
    path: '/redirect',
    component: Layout,
    meta: { hidden: true },
    children: [
      {
        path: '/redirect/:path*',
        component: () => import('@TG/views/redirect/index.vue')
      }
    ]
  },
  {
    path: '/login',
    component: () => import('@TG/views/login/index.vue'),
    meta: { hidden: true }
  },
  {
    path: '/404',
    component: () => import('@TG/views/error-page/404.vue'),
    meta: { hidden: true }
  },
  {
    path: '/401',
    component: () => import('@TG/views/error-page/401.vue'),
    meta: { hidden: true }
  },
  {
    path: '/',
    component: Layout,
    redirect: '/dashboard',
    children: [
      {
        path: '/dashboard',
        component: () => import('@TG/views/dashboard/index.vue'),
        name: 'Dashboard',
        meta: {
          title: 'dashboard',
          icon: 'dashboard',
          affix: true
        }
      }
    ]
  }
]

const createRouter = () => {
  return new Router({
    // mode: 'history', // Disabled due to Github Pages doesn't support this, enable this if you need.
    scrollBehavior: (to, from, savedPosition) => {
      if (savedPosition) {
        return savedPosition
      } else {
        return { x: 0, y: 0 }
      }
    },
    base: process.env.BASE_URL,
    routes: constantRoutes
  })
}

const router = createRouter()

export default router

/**
 * 重置路由器（清空路由）
 */
export const resetRouter = () => {
  (router as any).matcher = (createRouter() as any).matcher
}

const routeConfigList: RouteConfig[] = []
const routeConfigStorer = new Map<any, RouteConfig>()

/**
 * 初始化 initRouteConfigStorer
 * @param routeConfigs 路由配置集
 * @param parentFullPath 父级全路径
 */
const initRouteConfigStorer = (routeConfigs: RouteConfig[], parentFullPath: string = '') => {
  if (isNotEmpty(routeConfigs)) {
    routeConfigs.forEach(routeConfig => {
      const path = routeConfig.path
      const children = routeConfig.children || []
      let fullPath = ''
      if (path.startsWith('/')) {
        // 路径以 / 开头表示为完整路径
        fullPath = path
      } else {
        // 否则需要以上级完整路径拼装当前路径
        fullPath = `${parentFullPath}/${path}`
      }
      const name = routeConfig.name // 当为指定 name，则取 fullPath 为键
      routeConfig.meta = Object.assign({}, routeConfig.meta, { fullPath })
      // 进行 name、fullPath 双映射提高容错率
      if (isNotEmpty(name)) {
        routeConfigStorer.set(name, routeConfig)
      }
      routeConfigStorer.set(fullPath, routeConfig)
      initRouteConfigStorer(children, fullPath)
    })
  }
}

/**
 * 添加路由配置集
 * @warn RouteConfig.name 在 vue-router 中为非必填，但是在此约定 name 必填且唯一 [默认值为 fullPath]
 * @param routeConfig 路由配置集
 */
export const addRouteConfigs = (...routeConfigs: RouteConfig[]) => {
  if (isNotEmpty(routeConfigs)) {
    initRouteConfigStorer(routeConfigs)
    routeConfigList.push(...routeConfigs)
  }
}

/**
 * 获取路由配置集
 * @return 路由配置集
 */
export const getRouteConfigs = () => {
  return routeConfigList
}

/**
 * 获取路由配置
 * @param name 路由名 | 完整路径
 * @return 路由配置
 */
export const getRouteConfig = (name: string) => {
  return routeConfigStorer.get(name)
}

/**
 * 重定向路由
 * @param router 路由器
 * @param to 重定向到 [name | RouteConfig]
 */
export const redirect = (router: Router, to: any) => {
  let routeConfig: RouteConfig | null = null
  if (getDataType(to) === 'string') {
    routeConfig = getRouteConfig(to) || null
  } else {
    routeConfig = to
  }
  if (isNotEmpty(routeConfig)) {
    const fullPath = routeConfig?.meta.fullPath
    if (isNotEmpty(fullPath)) {
      router.push({ path: fullPath })
    }
  }
}
